//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Linq;

using ProjectBase.Core;
using ProjectBase.Core.Service;

using $prjsn$.Entity;
using $prjsn$.Common;
using $prjsn$.Common.Data;
using $prjsn$.Common.Business;

namespace $safeprojectname$
{
    /// <summary>
    ///   All Business checks for 'CustomList' on CRUD operations
    ///   are managed by: CustomListFacade
    /// </summary>
    public class CustomListFacade : CodeListFacade<CustomList, CustomListFilter, ICustomListDao>, ICustomListFacade
    {
        #region IBaseFacade<T> override - FACTORY METHOD

        /// <summary>
        /// Factory Method pattern.
        /// A central and only point for creating new entity of the type CustomList.
        /// </summary>
        /// <returns>new entity 'CustomList' transient</returns>
        public override CustomList CreateNew()
        {
            var entity = base.CreateNew();

            // TODO preset entity
            return entity;
        }

        /// <summary>
        /// Needed for the BaseFacade checks on Update() and Delete().
        /// </summary>
        /// <returns></returns>
        public override CustomListFilter CreateNewFilter()
        {
            var filter = base.CreateNewFilter();
            // TODO preset filter
            return filter;
        }

        #endregion IBaseFacade<T> override - FACTORY METHOD

        #region override Read

        public override CustomList GetById(int id)
        {
            var entity = base.GetById(id);
            if (entity.IsNull())
            {
                return null;
            }

            // check the SubType
            if (entity.CustomListType.Equals(GetCustomListType(entity.CustomListType)))
            {
                return entity;
            }
            this.PublishError(Str.Messages.CustomListIncorrectType3, entity.ID, entity.CustomListTypeName, CustomListTypeName);
            return null;
        }

        public override IEnumerable<CustomList> Find(CustomListFilter filter)
        {
            filter.CustomListType = GetCustomListType(filter.CustomListType);
            return base.Find(filter);
        }

        #endregion override Read

        #region override Write

        public override CustomList Add(CustomList entity)
        {
            // null handling in base
            if (entity.IsNull())
            {
                return base.Add(entity);
            }

            // new without Type
            if (entity.CustomListType.IsNull())
            {
                entity.CustomListType = GetCustomListType(null);
            }

            // check the SubType
            if (entity.CustomListType.Equals(GetCustomListType(entity.CustomListType)))
            {
                return base.Add(entity);
            }

            this.PublishError(Str.Messages.CustomListIncorrectType3, entity.ID, entity.CustomListTypeName, CustomListTypeName);
            return null;
        }

        public override CustomList Update(CustomList entity)
        {
            // null handling in base
            if (entity.IsNull())
            {
                return base.Update(entity);
            }

            // check the SubType
            if (entity.CustomListType.Equals(GetCustomListType(entity.CustomListType)))
            {
                return base.Update(entity);
            }

            this.PublishError(Str.Messages.CustomListIncorrectType3, entity.ID, entity.CustomListTypeName, CustomListTypeName);
            return null;
        }

        public override void Delete(CustomList entity)
        {
            // null handling in base
            if (entity.IsNull())
            {
                base.Delete(entity);
            }

            // check the SubType
            if (entity.CustomListType.Equals(GetCustomListType(entity.CustomListType)))
            {
                base.Delete(entity);
                return;
            }
            this.PublishError(Str.Messages.CustomListIncorrectType3, entity.ID, entity.CustomListTypeName, CustomListTypeName);
        }

        #endregion override Write

        #region ICustomListFacade

        // TODO any application dependent operations,
        // declared in ICustomListFacade
        // put here (e.g. 'public virtual bool IsOtherEntityInUse(OtherEntity item)')

        #endregion ICustomListFacade

        #region CustomList

        protected virtual CustomListType GetCustomListType(CustomListType existing)
        {
            if (CustomListTypeName.IsNull())
            {
                return existing;
            }

            CustomListType customType;
            if (CustomTypeDictionary.TryGetValue(CustomListTypeName.ToLowerInvariant(), out customType))
            {
                return customType;
            }
            return null;
        }

        private static IDictionary<string, CustomListType> _customTypeDictionary;

        private static IDictionary<string, CustomListType> CustomTypeDictionary
        {
            get
            {
                var customTypeDictionary = _customTypeDictionary;
                if (customTypeDictionary.IsNull())
                {
                    // types facade
                    var customListTypeFacade = Factory.CreateInstance<ICustomListTypeFacade>();

                    // get all, hang on the Change
                    customListTypeFacade.Change += Clear;
                    var customListTypes = customListTypeFacade.GetAll();

                    // to dictionary
                    customTypeDictionary = customListTypes
                        .ToDictionary(clt => clt.Description.ToLowerInvariant()
                                      , clt => clt);

                    _customTypeDictionary = customTypeDictionary;
                }
                return customTypeDictionary;
            }
        }

        private static void Clear(object sender, EventArgs e)
        {
            _customTypeDictionary = null;
        }

        #endregion CustomList

        #region properties

        public virtual string CustomListTypeName { get; set; }

        #endregion properties
    }
}